<template>
    <div class="container">
        <div class="chart-content">
            <div :id="container" class="chart-views"></div>
        </div>
    </div>
</template>
<script>
import Highcharts from 'highcharts';
import Highmaps from 'highcharts/modules/map.js'
import Highdrilldown from 'highcharts/modules/drilldown.js'
import { formatterNumber } from '@/common/js/util.js'
// import Highexporting from 'highcharts/modules/exporting.js'

// 关键步骤
Highmaps(Highcharts); // 地图
Highdrilldown(Highcharts); // 钻取 - 是改变展现数据维度的层次
// Highexporting(Highcharts); // 导出保存

export default {
    props: ['dataArr', 'container'],
    data() {
        return {
            charts: null,
            mapData: null, // 省份地图数据
            mapCityData: null, // 市区地图数据
            callBack: null,
            bgColor: '#DDEDFF' // 初始背景色
        }
    },
    created() {
        // 校正中国地图数据
        (H => {
            if(H.geojson) {
                H.geojson = function (geojson, hType, series) {
                    var mapData = [], path = [], polygonToPath = function (polygon) {
                        polygon.forEach(function (point, i) {
                            // fixed 
                            point = [point[0]*0.75, point[1] ];
                            if (i === 0) {
                                path.push(['M', point[0], -point[1]]);
                            }
                            else {
                                path.push(['L', point[0], -point[1]]);
                            }
                        });
                    };
                    hType = hType || 'map';
                    geojson.features.forEach(function (feature) {
                        var geometry = feature.geometry, type = geometry.type, coordinates = geometry.coordinates, properties = feature.properties, point;
                        path = [];
                        if (hType === 'map' || hType === 'mapbubble') {
                            if (type === 'Polygon') {
                                coordinates.forEach(polygonToPath);
                                path.push(['Z']);
                            }
                            else if (type === 'MultiPolygon') {
                                coordinates.forEach(function (items) {
                                    items.forEach(polygonToPath);
                                });
                                path.push(['Z']);
                            }
                            if (path.length) {
                                point = { path: path };
                            }
                        }
                        else if (hType === 'mapline') {
                            if (type === 'LineString') {
                                polygonToPath(coordinates);
                            }
                            else if (type === 'MultiLineString') {
                                coordinates.forEach(polygonToPath);
                            }
                            if (path.length) {
                                point = { path: path };
                            }
                        }
                        else if (hType === 'mappoint') {
                            if (type === 'Point') {
                                point = {
                                    x: coordinates[0],
                                    y: -coordinates[1]
                                };
                            }
                        }
                        if (point) {
                            mapData.push(H.extend(point, {
                                name: properties.name || properties.NAME,
                                /**
                                 * In Highmaps, when data is loaded from GeoJSON, the GeoJSON
                                 * item's properies are copied over here.
                                 *
                                 * @requires modules/map
                                 * @name Highcharts.Point#properties
                                 * @type {*}
                                 */
                                properties: properties
                            }));
                        }
                    });
                    // Create a credits text that includes map source, to be picked up in
                    // Chart.addCredits
                    if (series && geojson.copyrightShort) {
                        series.chart.mapCredits = H.format(series.chart.options.credits.mapText, { geojson: geojson });
                        series.chart.mapCreditsFull = H.format(series.chart.options.credits.mapTextFull, { geojson: geojson });
                    }
                    return mapData;
                };
            }
        })(Highcharts);
            
        // 设置钻取，返回按钮的文字, 样式在drilldown 里设置
        Highcharts.setOptions({
            lang: {
                drillUpText: '返回上级' // {series.name}
            }
        })
    },
    methods: {
        getMaps(drilldown = 'china', callBack = null) {
            if(drilldown == 'chain') {
                // 请求车家佳测试服服接口
                this.$http.get('/http/geojson/js/china.json').then(res => {
                    callBack(res)
                }).catch(err => {
                    this.$message.error(err);
                })
            } else {
                // 请求highcharts 中国官方数据接口
                $.getJSON('https://geojson.cn/data/' + drilldown + '.json', res => {
                    callBack(res)
                }, err => {
                    this.$message.error(err);
                })
            }
        },
        defaultData(mapData = {}) {
            let data = [];
            mapData.features.forEach((md, index) => {
                var tmp = {
			    	name: md.properties.name,
			    	value: 0,
                    color: this.bgColor
			    };
			    if(md.properties.filename) { // 南海诸岛 没有 md.properties.filename
			    	tmp.drilldown = md.properties.filename;
			    }
                if(md.properties.name === '南海诸岛') {
                    md.properties.fullname = md.properties.name;
                } else if(md.properties.name === '内蒙古') {
                    md.properties.offset = [md.properties.offset[0] + 0.05, md.properties.offset[1] + 0.05]; // 微调标签位置
                } else if(md.properties.name === '河北') {
                    md.properties.offset[0] = md.properties.offset[0] + 0.18
                } else if(md.properties.name === '陕西') {
                    md.properties.offset[0] = md.properties.offset[0] - 0.08
                    md.properties.offset[1] = md.properties.offset[1] + 0.18
                } else if(md.properties.name === '黑龙江') {
                    md.properties.offset[0] = md.properties.offset[0] + 0.08
                    md.properties.offset[1] = md.properties.offset[1] + 0.12
                } else if(md.properties.name === '甘肃') {
                    md.properties.offset[0] = md.properties.offset[0] + 0.03
                    md.properties.offset[1] = md.properties.offset[1] + 0.12
                }
                if(md.properties.filename) {
                    md.drilldown = md.properties.filename;
                }
                if(md.properties.offset){
                    md.properties['hc-middle-x'] = md.properties.offset[0];
                    md.properties['hc-middle-y'] = md.properties.offset[1];
                }

                data.push(tmp);
            })
            this.mapData = mapData;
            return [data, mapData];
        },
        chartInit(mapData = {}) {
            const that = this, defaultData = that.defaultData(mapData), dataArr = that.dataArr;
            this.charts = new Highcharts.mapChart(this.container, {
                chart: {
                    type: 'map',
                    backgroundColor: '#001230', // 背景色
                    events: {
                        // 钻取 点击进入下一级
                        drilldown: function(e) {
                            if(dataArr.drillEnabled) { // 开启下钻
                                that.drilldown(e);
                                dataArr.isDrilldown = true;
                            }
                        },
                        // 钻取 点击返回按钮
					    drillup: function(e) {
					    	that.charts.setTitle({
					    		text: '' // e.seriesOptions.name
					    	});
                            dataArr.isDrilldown = false;

                            // 判断搜索条件是否已变更，变更返回父级地图则需要重新请求
                            if(dataArr.isUpdate > 1) {
                                that.$emit("getData");
                            }
                            dataArr.isUpdate = 0;
					    }
                    }
                },
                title: {
                    text: '',
                    style: {
                        color: '#D0D6DD',
                        fontSize: '14px',
                    }
                },
                credits: { enabled: false },  // 去版权水印
                exporting: { enabled: false }, // 隐藏导出
                colorAxis: {
                    min: 0,
                    minColor: '#BFDEFF', //最浅颜色
                    maxColor: '#00377B', // 最深颜色 
                    gridLineWidth: 0, // 图例 分割线宽度
                    marker: {
                        color: '#F2B142' // 图例小三角形的填充颜色
                    },
                    labels: { 
			        	style: {
			        		color: "#8C97AA", 
			        	}
			        },
                },
                plotOptions: {
                    map: {
                        borderColor: '#AFB9CA', // 区域分割线颜色
                        borderWidth: 0.5,      // 分割线宽度
                        joinBy: 'name',   // 根据 name 属性进行关联
                        allowPointSelect: false, // 允许区域选中
                        dataLabels: {
                            enabled: true, // 显示地图标签
                            allowOverlap: true, // 开启标签重叠
                            format: '{point.name}',
                            color: '#ffffff', // 字体颜色
                            style: {
                                fontSize: '12px',
                                textOutline: 'none', // 去阴影
                                fontWeight: 'normal',
                                display: 'none' // 通过这种方式来隐藏标签，不采用通过控制 enabled 
                            },
                            crop: false,
                            overflow: 'none',
                        },
                        states: {
                            hover: {
                                color: '#F2B142', // 鼠标划过的背景颜色,
                            },
                            select: {
                                color: '#F2B142' // 选中的背景颜色
                            }
                        },
                        cursor: 'pointer',
                    },
                    series: {
                        point: {
                            events: {
                                // 点击选中, 支持多选
                                click: function() { 
                                    /*
                                    const chart = this.series.chart;
                                    let points = chart.getSelectedPoints();
                                    for(let value of points) {
                                        if (value.name == this.name) {
                                            this.select(false, true)
                                            return false;
                                        }
                                    }
                                    this.select(true, true)
                                    return false;
                                    */
                                },
                                // 选中事件
					            select: function () {
                                    // const chart = this.series.chart;
                                    // const show = !this.dataLabels || this.dataLabels.enabled ? true : false;
                                    this.update({
                                        dataLabels: {
                                            //enabled: true, // 显示标签, 这里不采用enabled方式(有bug)，采用下面display 来控制显示隐藏
                                            style: {
                                                display: 'inline'
                                            },
                                        }
                                    });
					            },
                                // 未选中事件
					            unselect: function () {
                                    this.update({
                                        dataLabels:{
                                            //enabled: false,
                                            style: {
                                                display: 'none'
                                            },
                                        }
                                    });
					            },
                                /**/
                                mouseOver() {
                                    const chart = this.series.chart;
                                    let points = chart.getSelectedPoints().find(item => {
                                        if(item.name == this.name) {
                                            return item;
                                        }
                                    }) || [];
                                    if(points.length < 1) {
                                        /*
                                        采用 this.udpate 快速滑动有卡顿
                                        this.update({
                                            color: '#F2B142',
                                            dataLabels:{
                                                style: {
                                                    display: 'inline'
                                                },
                                            }
                                        });
                                        */
                                        // 采用原生js 来实现滑动显示文字
                                        const nodes = document.querySelectorAll(".spread-map .highcharts-data-label tspan") || [];
                                        for(let node of nodes.values()) {
                                            if(node.innerHTML == this.name) {
                                                node.parentNode.parentNode.style.display = 'inline'
                                                break;
                                            }
                                        }
                                    }
                                },
                                mouseOut() {
                                    const chart = this.series.chart;
                                    let points = chart.getSelectedPoints().find(item => {
                                        if(item.name == this.name) {
                                            return item;
                                        }
                                    }) || [];
                                    if(points.length < 1) {
                                        /*
                                        const color = parseInt(this.value) > 0 ? undefined : that.bgColor;
                                        this.update({
                                            color,
                                            dataLabels:{
                                                style: {
                                                    display: 'none'
                                                },
                                            }
                                        });
                                        */
                                        const nodes = document.querySelectorAll(".spread-map .highcharts-data-label tspan") || [];
                                        for(let node of nodes.values()) {
                                            if(node.innerHTML == this.name) {
                                                node.parentNode.parentNode.style.display = 'none'
                                                break;
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }   
                },
                tooltip: {
                    borderRadius: 6, 
                    borderWidth: 0,
                    backgroundColor: 'rgba(255, 255, 255, 0.9)',
                    useHTML: true,
                    formatter: function() {
                        const valueSuffix = dataArr.tooltip ? dataArr.tooltip.valueSuffix : '人',
                              color = '#F2B142'; // this.point.color
                        return `<small style="margin-bottom:5px;display:block">${this.point.properties.fullname}</small><span style="color:${color};font-size:14px">●</span> ${this.point.series.name}: ${formatterNumber(this.point.value, 100000, 2, true)}${valueSuffix}<br/>`; // this.point.name - 简称
                    },
                    padding: 12,
                },
                legend: {
                   enabled: true,
                   align: 'center',
                },
                mapNavigation: { // 地图缩放控件
                    enabled: false,
                    buttonOptions: {
                        verticalAlign: 'bottom'
                    }
                },
                drilldown: {
                    activeDataLabelStyle: {
                        color: '#ffffff', // 当设置了钻取，需要从这里设置标签颜色
                        fontSize: '12px',
                        textOutline: 'none', // 去阴影
                        fontWeight: 'normal',
                        textDecoration: 'none'
                    },
                    drillUpButton: { // 返回按钮的位置及样式设置
                        position: {
                            x: 0,
                            y: 0
                        },
                        relativeTo: 'spacingBox', //相对位置
                        theme: {
                            height: 15,
                            paddingLeft: 3
                        }
                    }
                },
                series: [{
                    name: '',
                    data: defaultData[0],
                    mapData: defaultData[1],
                }]
            });

            if(this.callBack) {
                typeof this.callBack == "function" && this.callBack(); // 执行回调
                this.callBack = null;
            }
        },
        drilldown(event) { // 钻取
            const map = this.charts;
            map.tooltip.hide();

            // 异步下钻
            if (event.point.drilldown) {
                // map.showLoading('下钻中，请稍后...');
                this.getMaps(event.point.drilldown, data => {
                    if(!data) return;
                    this.$emit("getData"); // 数据获取
                    data = Highcharts.geojson(data);
                    this.mapCityData = data;
                    
                    data.forEach(d => {
                        if(d.properties.filename) {
                            d.drilldown = d.properties.filename;
                        }
                        if(d.properties.offset){
                            d.properties['hc-middle-x'] = d.properties.offset[0];
                            d.properties['hc-middle-y'] = d.properties.offset[1];
                        }
                        d.value = 0;
                        d.color = this.bgColor;
                    });
                    // map.hideLoading();
                    map.addSeriesAsDrilldown(event.point, {
                        name: this.dataArr.series[0].name,
                        data: data,
                    });
                    if(this.callBack) {
                        typeof this.callBack == "function" && this.callBack();
                        this.callBack = null;
                    }
                    /* // 设置标题
				    map.setTitle({
				    	text: event.point.properties.fullname
				    });
                    */
                })
            }
        },
        updateChart(val) {
            if(this.charts) {
                const features = this.mapData.features;
                let data = [];
                features.forEach(item => {
                    const obj = val[0].data.find(item2 => item2.name == item.properties.name);
                    let o = {
                        name: item.properties.name,
                        value: obj && obj.value || 0
                    }
                    o.color = obj && o.value > 0 ? undefined : this.bgColor;
                    if(item.drilldown) o.drilldown = item.drilldown;
                    data.push(o)
                })
                val[0].data = data;
                this.charts.update({
                    series: val
                })
            } else {
                this.callBack = function() {
                    this.updateChart(val)
                };
            }
        },
        updateDrilldown(val) {
            if(this.mapCityData) {
                const features = this.mapCityData;
                let data = [];
                features.forEach(item => {
                    const obj = val[0].data.find(item2 => item2.name == item.properties.name);
                    let o = {
                        name: item.properties.name,
                        drilldown: item.drilldown,
                        value: obj && obj.value || 0
                    }
                    o.color = obj && o.value > 0 ? undefined : this.bgColor;
                    data.push(o)
                })
                val[0].data = data;
                this.charts.update({
                    series: val
                })
            } else {
                this.callBack = function() {
                    this.updateDrilldown(val)
                };
            }
        }
    },
    mounted() {
        this.getMaps('china', res => {
            this.chartInit(res)
        })
    },
    watch: {
        'dataArr.series': function(val, oldVal) {
            if(!this.dataArr.isDrilldown) {
                // 全国地图更新
                this.updateChart(val)
            } else {
                // 下钻 省级数据更新
                this.updateDrilldown(val)
            }
        }
    }
}
</script>
<style lang="scss" scoped>
    .container, .chart-views{
        width: 100%;
        height: 100%;
    }
    .chart-content {
        box-sizing: border-box;
        width: 100%;
        height: 100%;
        padding: 30px 0 0 0;
    }
    // 设置图例 色条 圆角
    /deep/.highcharts-legend-item rect {
        rx: 10;
        // ry: 10;
        height: 13px;
    }
</style>